<script setup lang="ts">
import { computed, ref, watch } from 'vue';

import { FormCreateItem, FormCreateType } from '@/types/form-create';
import { FormInst, FormRules } from 'naive-ui';

import { QTableSearchProps } from './type';

const props = withDefaults(defineProps<QTableSearchProps>(), {
	items: () => [],
	inline: true,
	showReset: true,
});

const emit = defineEmits<{
	(e: 'search', values: Record<string, any>): void;
	(e: 'reset'): void;
}>();

const formRef = ref<FormInst | null>(null);

const formData = ref<Record<string, any>>(props.initialValues ?? {});

const rules = computed<FormRules>(() => {
	return props.items.reduce((acc, item) => {
		if (item.field && item.validate) {
			acc[item.field] = item.validate;

			item.control?.forEach((control) => {
				if (control.handle(formData.value, formRef.value)) {
					control.items.forEach((item) => {
						if (item.field && item.validate) {
							acc[item.field] = item.validate;
						}
					});
				}
			});
		}
		return acc;
	}, {} as FormRules);
});

const formItems = computed(() => {
	const data = props.items.reduce((acc, item) => {
		acc.push(item);
		acc.push(...(item.control?.filter((control) => control.handle(formData.value, formRef.value))?.flatMap((control) => control.items) ?? []));
		return acc;
	}, [] as FormCreateItem[]);

	return data;
});

const handleSearch = () => {
	formRef.value?.validate().then((valid) => {
		if (valid) {
			emit('search', formData.value);
		}
	});
};

const handleReset = () => {
	reset();
	emit('reset');
};

const reset = () => {
	formData.value = props.initialValues ? { ...props.initialValues } : {};
};

const setValues = (values: Record<string, any>, type: 'cover' | 'merge' = 'cover') => {
	if (type === 'cover') {
		formData.value = values;
	} else {
		formData.value = { ...formData.value, ...values };
	}
};

const getValues = () => {
	return formData.value;
};

const validate = (callback: (error: boolean) => void) => {
	formRef.value?.validate((error) => {
		callback(!!error);
	});
};

// 暴露方法
defineExpose({
	formRef,
	setValues,
	reset,
	validate,
	getValues,
});
</script>

<template>
	<n-card size="small">
		<n-form
			class="flex flex-wrap gap-y-3"
			ref="formRef"
			:show-feedback="false"
			:show-require-mark="false"
			:inline="inline"
			label-placement="left"
			:label-width="labelWidth"
			:rules="rules"
			:model="formData"
		>
			<template v-for="item in formItems" :key="item.field">
				<n-form-item v-if="item.permission ? $hasPermission(item.permission) : true" :label="item.title" :path="item.field" v-bind="item.wrap">
					<template #label>
						<div class="flex items-center">
							<span>
								{{ item.title }}
							</span>
							<n-tooltip trigger="hover" v-if="item.info">
								<template #trigger>
									<i class="icon-[ant-design--question-circle-outlined]"></i>
								</template>
								{{ item.info }}
							</n-tooltip>
						</div>
					</template>
					<form-item-map :item="item" :form-data="formData">
						<template v-for="(slot, name) in $slots" #[name]="scope">
							<slot :name="name" v-bind="{ ...scope, formData, formRef }" />
						</template>
					</form-item-map>
				</n-form-item>
			</template>

			<div class="flex gap-x-2">
				<n-button type="primary" @click="handleSearch">搜索</n-button>
				<n-button @click="handleReset">重置</n-button>
			</div>
		</n-form>
	</n-card>
</template>

<style scoped></style>
